#include <cstring>
#include <iostream>
#include <string>
#include <vector>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/epoll.h>
using namespace std;
static const uint16_t port = 8080;
struct conn_t
{
    conn_t()
        : net_fd(-1), alive(0), last_time(0)
    {
    }
    conn_t(const int fd, const int al, time_t t)
        : net_fd(fd), alive(al), last_time(t)
    {
    }
    int net_fd;
    int alive;
    time_t last_time;
};
int main(int argc, char *argv[])
{
    int socket_fd = socket(AF_INET, SOCK_STREAM, 0);
    int reuse = 1;
    setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
    struct sockaddr_in local;
    local.sin_family = AF_INET;
    local.sin_addr.s_addr = htonl(INADDR_ANY);
    local.sin_port = htons(port);
    bind(socket_fd, (struct sockaddr *)&local, sizeof(local));
    listen(socket_fd, 10);
    vector<conn_t> list;
    list.resize(100);
    int epoll_fd = epoll_create(1);
    struct epoll_event event;
    event.events = EPOLLIN;
    event.data.fd = socket_fd;
    epoll_ctl(epoll_fd, EPOLL_CTL_ADD, socket_fd, &event);
    while (true)
    {
        struct epoll_event array[10];
        memset(array, 0, sizeof(array));
        int num = epoll_wait(epoll_fd, array, 10, 1000);
        for (int i = 0; i < num; i++)
        {
            int fd = array[i].data.fd;
            if (fd == socket_fd)
            {
                int net_fd = accept(socket_fd, nullptr, nullptr);
                list.push_back(conn_t(net_fd, 0, time(nullptr)));
                event.data.fd = net_fd;
                epoll_ctl(epoll_fd, EPOLL_CTL_ADD, net_fd, &event);
            }
            else
            {
                char buffer[1024] = {0};
                int ret_recv = recv(fd, buffer, sizeof(buffer), 0);
                if (ret_recv == 0)
                {
                    for (int j = 0; j < list.size(); j++)
                    {
                        if (list[j].alive == 0 && list[j].net_fd == fd)
                        {
                            list[j].alive = 1;
                            break;
                        }
                    }
                    epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, nullptr);
                    close(fd);
                    continue;
                }
                for (int k = 0; k < list.size(); k++)
                {
                    if (list[k].alive == 0 && list[k].net_fd != fd)
                    {
                        send(list[k].net_fd, buffer, ret_recv, 0);
                    }
                    else if (list[k].alive == 0 && list[k].net_fd == fd)
                    {
                        time(&list[k].last_time);
                    }
                }
            }
        }
        for (int k = 0; k < list.size(); k++)
        {
            time_t now_time;
            time(&now_time);
            if (list[k].alive == 0 && (now_time - list[k].last_time) >= 30)
            {
                epoll_ctl(epoll_fd, EPOLL_CTL_DEL, list[k].net_fd, nullptr);
                list[k].alive = 1;
                close(list[k].net_fd);
            }
        }
    }
    close(socket_fd);
    return 0;
}